package ink.xiaobaibai.service.impl;

import ink.xiaobaibai.common.SmsVerificationCode;
import ink.xiaobaibai.service.ICodeSendService;
import ink.xiaobaibai.service.ISmsCodeSender;
import ink.xiaobaibai.units.IpUnit;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;

/**
 * @description: 短信验证码生成类
 * @author: 小白白
 * @create: 2021-05-15
 **/

@Service
@Slf4j
public class SmsCodeCreateServiceImpl implements ICodeSendService {

    public static final String SMS_CODE_PREFIX = "smsCode:";

    @Autowired
    private ISmsCodeSender smsCodeSender;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public SmsVerificationCode createCode(HttpServletRequest request) {
        //发送验证码
        SmsVerificationCode smsVerificationCode = new SmsVerificationCode(request.getParameter("phone"));
        if (!smsVerificationCode.isValidPhone() || !this.beforeProcessor(request, smsVerificationCode.getCode())) {
            //终止发送
            log.info("手机号未通过校验或号码冷却中");
            return null;
        }
        //通过校验可以发送
        this.smsCodeSender.sendVerCode(smsVerificationCode.getPhone(), smsVerificationCode.getCode());
        return smsVerificationCode;
    }

    private boolean beforeProcessor(HttpServletRequest request, String code) {

        String ip = IpUnit.getRemoteAddr(request);
        Long increment = this.stringRedisTemplate.opsForValue().increment(SMS_CODE_PREFIX + ip);
        this.stringRedisTemplate.expire(SMS_CODE_PREFIX + ip, 3, TimeUnit.HOURS);
        if (increment > 10) {
            //三小时内,发送了十条
            this.stringRedisTemplate.expire(SMS_CODE_PREFIX + ip, 1, TimeUnit.DAYS);
            return false;
        }

        String phone = request.getParameter("phone");
        if (StringUtils.isBlank(phone)) {
            return false;
        }
        //不存在就赋值,并返回true; 存在则不操作,返回false
        return this.stringRedisTemplate.opsForValue().setIfAbsent(SMS_CODE_PREFIX + phone, code, 65, TimeUnit.SECONDS);
    }

}
